﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;
using java.math;

namespace EpcTagLibrary
{
    public static class Common
    {
        public static bool IsBinaryString(string str)
        {
            return IsFrom(str, "01");
        }

        public static bool IsDecimalString(string str)
        {
            return IsFrom(str, "0123456789");
        }

        public static bool IsHexString(string str)
        {
            return IsFrom(str, "0123456789abcdefABCDEF");
        }

        private static bool IsFrom(string str, string pattern)
        {
            foreach (char c in str)
            {
                if (!pattern.Contains(c))
                {
                    return false;
                }
            }

            return true;
        }

        public static Bits Concat(Bits baseBits, Bits addBits)
        {
            Bits Result = new Bits(baseBits.Length + addBits.Length);

            for (int i = 0; i < baseBits.Length; i++)
            {
                Result[i] = baseBits[i];
            }

            for (int i = 0; i < addBits.Length; i++)
            {
                Result[i + baseBits.Length] = addBits[i];
            }

            return Result;
        }

        public static bool IsLegalChar(char c)
        {
            if ((c == 33) || (c == 34))
            {
                return true;
            }
            else if ((c >= 37) && (c <= 63))
            {
                return true;
            }
            else if ((c >= 65) && (c <= 90))
            {
                return true;
            }
            else if (c == 95)
            {
                return true;
            }
            else if ((c >= 97) && (c <= 122))
            {
                return true;
            }

            return false;
        }

        public static Bits ToBits(byte b)
        {
            return ToBits(System.Convert.ToChar(b));
        }

        public static Bits ToBits(char c)
        {
            Bits Result = new Bits(7);

            for (int i = 0; i < 7; i++)
            {
                Result[i] = ((c >> i) & 1) == 1;
            }

            return Result;
        }

        public static Bits ByteArrayToBits(byte[] bytes)
        {
            Bits Result = new Bits(bytes.Length * 8);

            for (int i = bytes.Length - 1; i >= 0; i--)
            {
                for (int j = 0; j < 8; j++)
                {
                    Result[((bytes.Length-1-i)*8)+j] = ((bytes[i] >> j & 1) == 1);
                }
            }

            return Result;
        }

        public static byte[] BitsToByteArray(Bits bits)
        {
            byte[] Result = new byte[bits.Length / 8];

            for (int i = bits.Length - 1; i >= 0; i--)
            {
                if (bits[i])
                {
                    Result[Result.Length - i / 8 - 1] |= (byte) (1 << (i % 8));
                }
            }

            return Result;
        }

        public static long BitsToInt(Bits bits)
        {
            StringBuilder Result = new StringBuilder();

            for (int i = bits.Length - 1; i >= 0; i--)
            {
                Result.Append(bits[i] ? "1":"0");
            }

            return System.Convert.ToInt64(Result.ToString(), 2);
        }

        public static Bits LongToBits(long num, int length)
        {
            string Temp = System.Convert.ToString(num, 2);

            if (Temp.Length > length)
            {
                throw new BitLengthException("Unable to Convert long " + num + "to Bits of length" + length);
            }

            Bits Result = new Bits(length);

            int Strart = length - Temp.Length;

            for (int i=0;i<Temp.Length;i++)
            {
                Result[i] = Temp[Temp.Length-i-1] == '1';
            }

            return Result;
        }

        public static byte[] RadixStringToByteArray(string str, int radix)
        {
            BigInteger Num = new BigInteger(str, radix);

            sbyte[] Temp = Num.toByteArray();

            int Length = Temp.Length;

            if (radix == 2)
            {
                Length = str.Length / 8;
            }
            else if (radix == 16)
            {
                Length = str.Length / 2;
            }

            byte[] Result = new byte[Length];

            int Start = (Temp.Length >= Result.Length) ? Temp.Length - Result.Length : 0;

            for (int i = Start; i < Temp.Length; i++)
            {
                Result[Result.Length-Temp.Length+i] = (byte)Temp[i];
            }

            return Result;
        }

        public static Bits StringToBits(string str)
        {
            byte[] Bytes = System.Text.Encoding.Default.GetBytes(str.Trim());

            return ByteArrayToBits(Bytes);
        }

        public static string BitsToRawHexString(Bits bits)
        {
            byte[] Bytes = BitsToByteArray(bits);

            StringBuilder Result = new StringBuilder();
            Result.Append("x");

            foreach (byte B in Bytes)
            {
                string Temp = System.Convert.ToString(B, 16);
                if (Temp.Length == 1)
                {
                    Result.Append("0");
                }

                Result.Append(Temp.ToUpper());
            }

            return Result.ToString();
        }

        public static string BitsToString(Bits bits)
        {
            byte[] Bytes = BitsToByteArray(bits);

            return System.Text.Encoding.Default.GetString(Bytes);
        }

        public static string BitsToPaddedInt(Bits bits, int length)
        {
            string Result = System.Convert.ToString(BitsToInt(bits));

            if (Result.Length < length)
            {
                Result = Result.PadLeft(length - Result.Length, '0');
            }

            return Result;            
        }
    }
}
